#include "NameGenerator.h"
#include <stdio.h>
#include <stdlib.h>

vector<vector<Pair>> NameGenerator::startingLetters;
vector<map<Pair, vector<char>>> NameGenerator::lettersOrder;

vector<Pair>* NameGenerator::pStartingLetters;
map<Pair, vector<char>>* NameGenerator::pLettersOrder;

NameGenerator::NameGenerator(void)
{
}


NameGenerator::~NameGenerator(void)
{
}

void NameGenerator::ParseData()
{
	char** namePatterns[] = {nordMale, nordFemale, whiteMale, whiteFemale, blackMale, blackFemale, cities};
	int nameCounts[] = {nordMaleSize, nordFemaleSize, whiteMaleSize, whiteFemaleSize, blackMaleSize, blackFemaleSize, citiesSize};

	for(int i=0; i<7; i++)
	{
		char** data = namePatterns[i];
		int elements = nameCounts[i];

		vector<Pair> startingLettersTemp;
		map<Pair, vector<char>> lettersOrderTemp;

		// For all names in the data table
		for(int i=0; i<elements; i++)
		{
			// Get two starting letters and make a pair from them
			Pair p(data[i][0], data[i][1]);
			startingLettersTemp.push_back(p);
			
			// For all letters in given name
			for(int index=0; ; index++)
			{
				// Make a pair from actual letter and next one
				Pair p(data[i][index], data[i][index+1]);
				if(p[1] == '\0') break;

				// Push letter after the pair to this pair vector
				lettersOrderTemp[p].push_back(data[i][index+2]);
			}
		}

		startingLetters.push_back(startingLettersTemp);
		lettersOrder.push_back(lettersOrderTemp);
	}
}

string NameGenerator::GenerateName(int aRace, bool aMale)
{
	static bool dataParsed = false;
	if(dataParsed == false)
	{
		ParseData();
		dataParsed = true;
	}

	int dictionarySet;
	if(aRace == RACE_NORD) dictionarySet = 0;
	if(aRace == RACE_WHITE) dictionarySet = 2;
	if(aRace == RACE_BLACK) dictionarySet = 4;
	if(!aMale) dictionarySet++;

	bool city = false;
	if(aRace == RACE_END)
	{
		city = true;
		dictionarySet = 6;
	}

	pStartingLetters = &startingLetters[dictionarySet];
	pLettersOrder = &lettersOrder[dictionarySet];

	char name[24];

	int i;
	int maxLetters = 7;
	if(city) maxLetters = 10;
	do
	{
		Pair initialPair = (*pStartingLetters)[rand()%pStartingLetters->size()];
		name[0] = initialPair.Get(0);
		name[1] = initialPair.Get(1);

		i = 2;
		for(;i<maxLetters;i++)
		{
			Pair actualPair(name[i-2],name[i-1]);
			vector<char> letters = (*pLettersOrder)[actualPair];

			bool quickBreak = false;
			if(city && i>maxLetters-2)
				for(unsigned int l=0; l<letters.size(); l++)
					if(letters[l] == '\0')
					{
						name[i] = '\0';
						quickBreak = true;
						break;
					}
			if(quickBreak) break;

			name[i] = letters[rand()%letters.size()];

			if(name[i] == '\0') break;
		}
	} while(name[2] == '\0' || (city && name[3] == '\0'));

	if(!aMale && i==maxLetters+1)
	{
		name[i] = 'a';
		i++;
	}
	name[i] = '\0';
	name[0] -= 32;

	string sname = name;
	return sname;
}

string NameGenerator::GenerateCityName()
{
	return GenerateName(RACE_END,true);
}